import mongoose, { Schema } from 'mongoose'
import {
  DynamicCollectionConfig,
  IDynamicCollectionConfig
} from '../models/dynamicCollection'
import { Counter } from '../models/counter'

class DynamicCollection {
  private models: Map<string, mongoose.Model<any>> = new Map()

  /**
   * 创建动态集合
   */
  async createCollection(
    config: Omit<IDynamicCollectionConfig, 'createdAt' | 'updatedAt'>
  ) {
    // 检查集合是否已存在
    const existingConfig = await DynamicCollectionConfig.findOne({
      collectionName: config.collectionName
    })

    if (existingConfig) {
      throw new Error(`Collection ${config.collectionName} already exists`)
    }

    // 构建Schema定义
    const schemaDefinition: Record<string, any> = {}

    // 添加自增ID字段
    schemaDefinition.id = {
      type: Number,
      unique: true,
    }

    config.fields.forEach((field) => {
      let fieldType: any
      switch (field.type) {
        case 'String':
          fieldType = String
          break
        case 'Number':
          fieldType = Number
          break
        case 'Boolean':
          fieldType = Boolean
          break
        case 'Date':
          fieldType = Date
          break
        case 'Array':
          fieldType = []
          break
        default:
          fieldType = String
      }

      schemaDefinition[field.name] = {
        type: fieldType,
        ...(field.required !== undefined && { required: field.required }),
        ...(field.defaultValue !== undefined && { default: field.defaultValue })
      }
    })

    // 添加基础字段
    schemaDefinition.createdAt = {
      type: Date,
      default: Date.now
    }

    schemaDefinition.updatedAt = {
      type: Date,
      default: Date.now
    }

    // 创建Schema
    const schema = new Schema(schemaDefinition, {
      collection: config.collectionName,
      timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' }
    })

    // 添加更新中间件
    schema.pre('findOneAndUpdate', function (next) {
      this.set({ updatedAt: new Date() })
      next()
    })

    // 在 pre('save') 钩子中确保 id 被赋值
    schema.pre('save', async function (next) {
      if (this.isNew) {
        try {
          // 为新文档生成自增ID
          const counter = await Counter.findByIdAndUpdate(
            { _id: config.collectionName },
            { $inc: { seq: 1 } },
            { new: true, upsert: true }
          )
          this.id = counter.seq
          
          this.createdAt = new Date()
          this.updatedAt = new Date()
          next()
        } catch (error: any) {
          next(error)
        }
      } else {
        this.updatedAt = new Date()
        next()
      }
    })

    // 保存配置到数据库
    const collectionConfig = new DynamicCollectionConfig({
      collectionName: config.collectionName,
      fields: config.fields
    })

    await collectionConfig.save()

    // 创建模型并缓存
    const model = mongoose.model(
      config.collectionName,
      schema,
      config.collectionName
    )
    this.models.set(config.collectionName, model)

    return {
      success: true,
      message: 'Collection created successfully',
      data: collectionConfig
    }
  }

  /**
   * 获取所有集合配置
   */
  async getAllCollections() {
    const collections = await DynamicCollectionConfig.find({})
    return collections
  }

  /**
   * 获取集合配置详情
   */
  async getCollectionByName(name: string) {
    const collection = await DynamicCollectionConfig.findOne({
      collectionName: name
    })
    if (!collection) {
      throw new Error(`Collection ${name} not found`)
    }
    return collection
  }

  /**
   * 删除集合配置
   */
  async deleteCollection(name: string) {
    // 删除配置记录
    const result = await DynamicCollectionConfig.deleteOne({
      collectionName: name
    })

    // 从缓存中移除模型
    this.models.delete(name)

    // 注意：MongoDB不会自动删除空集合，需要手动处理

    return {
      success: result.deletedCount > 0,
      message:
        result.deletedCount > 0
          ? 'Collection deleted successfully'
          : 'Collection not found'
    }
  }

  /**
   * 更新集合配置
   */
  async updateCollection(name: string, updateData: Partial<IDynamicCollectionConfig>) {
    // 检查集合是否存在
    const existingConfig = await DynamicCollectionConfig.findOne({
      collectionName: name
    })

    if (!existingConfig) {
      throw new Error(`Collection ${name} not found`)
    }

    // 更新配置
    const updatedConfig = await DynamicCollectionConfig.findOneAndUpdate(
      { collectionName: name },
      { $set: updateData },
      { new: true }
    )

    // 从缓存中移除旧模型
    this.models.delete(name)

    return {
      success: true,
      message: 'Collection updated successfully',
      data: updatedConfig
    }
  }

  /**
   * 向集合添加文档
   */
  async createDocument(collectionName: string, data: any) {
    const model = await this.getModel(collectionName)
    const document = new model(data)
    return await document.save()
  }

  /**
   * 查询集合中的文档
   */
  async findDocuments(
    collectionName: string,
    filter: any = {},
    options: any = {}
  ) {
    const model = await this.getModel(collectionName)
    const { page = 1, limit = 10 } = options

    // 处理模糊查询
    const processedFilter: any = {}
    const config = await this.getCollectionByName(collectionName)
    
    for (const [key, value] of Object.entries(filter)) {
      // 查找字段配置
      const fieldConfig = config.fields.find((f: any) => f.name === key)
      
      // 如果是字符串类型的字段且值为字符串，则使用模糊查询
      if (fieldConfig && fieldConfig.type === 'String' && typeof value === 'string') {
        processedFilter[key] = { $regex: value, $options: 'i' }
      } else {
        processedFilter[key] = value
      }
    }

    const documents = await model
      .find(processedFilter)
      .skip((page - 1) * limit)
      .limit(limit)
      .sort({ createdAt: -1 })

    const total = await model.countDocuments(processedFilter)

    return {
      data: documents,
      pagination: {
        page,
        limit,
        total,
        pages: Math.ceil(total / limit)
      }
    }
  }

  /**
   * 更新文档
   */
  async updateDocument(collectionName: string, id: string, data: any) {
    const model = await this.getModel(collectionName)
    return await model.findByIdAndUpdate(
      id,
      { $set: data },
      { new: true, runValidators: true }
    )
  }

  /**
   * 删除文档
   */
  async deleteDocument(collectionName: string, id: string) {
    const model = await this.getModel(collectionName)
    const result = await model.findByIdAndDelete(id)
    return {
      success: !!result,
      message: result ? 'Document deleted successfully' : 'Document not found'
    }
  }

  /**
   * 获取模型（内部方法）
   */
  private async getModel(collectionName: string): Promise<mongoose.Model<any>> {
    // 如果模型已在缓存中，直接返回
    if (this.models.has(collectionName)) {
      return this.models.get(collectionName)!
    }

    // 检查集合配置是否存在
    const config = await DynamicCollectionConfig.findOne({ collectionName })
    if (!config) {
      throw new Error(`Collection ${collectionName} not found`)
    }

    // 重新构建Schema
    const schemaDefinition: Record<string, any> = {}

    // 添加自增ID字段
    schemaDefinition.id = {
      type: Number,
      unique: true,
    }

    config.fields.forEach((field: any) => {
      let fieldType: any
      switch (field.type) {
        case 'String':
          fieldType = String
          break
        case 'Number':
          fieldType = Number
          break
        case 'Boolean':
          fieldType = Boolean
          break
        case 'Date':
          fieldType = Date
          break
        case 'Array':
          fieldType = []
          break
        default:
          fieldType = String
      }

      schemaDefinition[field.name] = {
        type: fieldType,
        ...(field.required !== undefined && { required: field.required }),
        ...(field.defaultValue !== undefined && { default: field.defaultValue })
      }
    })

    // 添加基础字段
    schemaDefinition.createdAt = Date
    schemaDefinition.updatedAt = Date

    // 创建Schema
    const schema = new Schema(schemaDefinition, {
      collection: collectionName,
      timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' }
    })

    // 添加更新中间件
    schema.pre('findOneAndUpdate', function (next) {
      this.set({ updatedAt: new Date() })
      next()
    })

    schema.pre('save', async function (next) {
      if (this.isNew) {
        try {
          // 为新文档生成自增ID
          const counter = await Counter.findByIdAndUpdate(
            { _id: collectionName },
            { $inc: { seq: 1 } },
            { new: true, upsert: true }
          )
          this.id = counter.seq
          
          if (!this.createdAt) {
            this.createdAt = new Date()
          }
          this.updatedAt = new Date()
          next()
        } catch (error: any) {
          next(error)
        }
      } else {
        this.updatedAt = new Date()
        next()
      }
    })

    // 创建模型并缓存
    let model: mongoose.Model<any>;
    if (mongoose.models[collectionName]) {
      // 如果模型已经存在，则直接使用已存在的模型
      model = mongoose.model(collectionName);
    } else {
      // 否则创建新模型
      model = mongoose.model(collectionName, schema, collectionName)
    }
    this.models.set(collectionName, model)

    return model
  }
}

export const dynamicCollectionService = new DynamicCollection()
